#include "HerzeleidPrecompiled.hxx"
#include "HerzeleidShapes.hxx"
using namespace HerzeleidRendererResourcesNamespaceImpl;

BasicShapes::BasicShapes( _In_ Device3Ptr pDevice ) : 
	m_Device(pDevice)
{
}

 Void BasicShapes::CreateVertexBuffer(
    _In_ UInt32 uiNumVertices,
    _In_ BasicVertexPtr pVertexData,
    _Out_ BufferAddress ppVertexBuffer
    )
{
	(*ppVertexBuffer) = nullptr; // Null the resulting value 

	WRL::ComPtr<Buffer> InternalVertexBuffer;

	D3D11_BUFFER_DESC InternalVertexBufferDesc;
	InternalVertexBufferDesc.ByteWidth = sizeof(BasicVertex) * uiNumVertices;
	InternalVertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	InternalVertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	InternalVertexBufferDesc.CPUAccessFlags = 0;
	InternalVertexBufferDesc.MiscFlags = 0;
	InternalVertexBufferDesc.StructureByteStride = 0;

	D3D11_SUBRESOURCE_DATA InternalVertexBufferData;
	InternalVertexBufferData.pSysMem = pVertexData;
	InternalVertexBufferData.SysMemPitch = 0;
	InternalVertexBufferData.SysMemSlicePitch = 0;

    DirectX::ThrowIfFailed( m_Device->CreateBuffer(
        _In_ (&InternalVertexBufferDesc),
        _In_ (&InternalVertexBufferData),
        _Outptr_opt_result_nullonfailure_ (&InternalVertexBuffer)		
        ) );
	
    (*ppVertexBuffer) = InternalVertexBuffer.Detach();
}

 Void BasicShapes::CreateTangentVertexBuffer(
    _In_ UInt32 uiNumVertices,
    _In_ TangentVertexPtr pVertexData,
    _Out_ BufferAddress ppVertexBuffer
    )
{
	(*ppVertexBuffer) = nullptr; // Null the resulting value 

	WRL::ComPtr<Buffer> InternalVertexBuffer;

	D3D11_BUFFER_DESC InternalVertexBufferDesc;
	InternalVertexBufferDesc.ByteWidth = sizeof(TangentVertex) * uiNumVertices;
	InternalVertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	InternalVertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	InternalVertexBufferDesc.CPUAccessFlags = 0;
	InternalVertexBufferDesc.MiscFlags = 0;
	InternalVertexBufferDesc.StructureByteStride = 0;

	D3D11_SUBRESOURCE_DATA InternalVertexBufferData;
	InternalVertexBufferData.pSysMem = pVertexData;
	InternalVertexBufferData.SysMemPitch = 0;
	InternalVertexBufferData.SysMemSlicePitch = 0;

    DirectX::ThrowIfFailed( m_Device->CreateBuffer(
        _In_ (&InternalVertexBufferDesc),
        _In_ (&InternalVertexBufferData),
        _Outptr_opt_result_nullonfailure_ (&InternalVertexBuffer)		
        ) );
	
    (*ppVertexBuffer) = InternalVertexBuffer.Detach();
}

Void BasicShapes::CreateIndexBuffer(
    _In_ UInt32 uiNumVertices,
    _In_ UInt16Ptr indexData,
    _Out_ BufferAddress ppIndexBuffer
    )
{
	(*ppIndexBuffer) = nullptr;
    Microsoft::WRL::ComPtr<ID3D11Buffer> InternalIndexBuffer;

    D3D11_BUFFER_DESC InternalIndexBufferDesc;
    InternalIndexBufferDesc.ByteWidth = sizeof(UInt16) * uiNumVertices;
    InternalIndexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    InternalIndexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
    InternalIndexBufferDesc.CPUAccessFlags = 0;
    InternalIndexBufferDesc.MiscFlags = 0;
    InternalIndexBufferDesc.StructureByteStride = 0;

    D3D11_SUBRESOURCE_DATA InternalIndexBufferData;
    InternalIndexBufferData.pSysMem = indexData;
    InternalIndexBufferData.SysMemPitch = 0;
    InternalIndexBufferData.SysMemSlicePitch = 0;

    DirectX::ThrowIfFailed(
        m_Device->CreateBuffer(
            _In_ (&InternalIndexBufferDesc),
            _In_ (&InternalIndexBufferData),
            _Outptr_opt_result_nullonfailure_ (&InternalIndexBuffer)
            )
        );

    (*ppIndexBuffer) = InternalIndexBuffer.Detach();
}



Void BasicShapes::CreateCube(
    _Out_ BufferAddress ppVertexBuffer,
    _Out_ BufferAddress ppIndexBuffer,
    _Out_opt_ UInt32Ptr uiVertexCount,
    _Out_opt_ UInt32Ptr uiIndexCount
	)
{
    BasicVertex CubeVertices[] =
    {
        { DirectX::XMFLOAT3A(-0.5f, 0.5f, -0.5f), DirectX::XMFLOAT3A( 0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2A(0.0f, 0.0f) }, // +Y (top face)
        { DirectX::XMFLOAT3A( 0.5f, 0.5f, -0.5f), DirectX::XMFLOAT3A( 0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2A(1.0f, 0.0f) },
        { DirectX::XMFLOAT3A( 0.5f, 0.5f,  0.5f), DirectX::XMFLOAT3A( 0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2A(1.0f, 1.0f) },
        { DirectX::XMFLOAT3A(-0.5f, 0.5f,  0.5f), DirectX::XMFLOAT3A( 0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2A(0.0f, 1.0f) },

        { DirectX::XMFLOAT3A(-0.5f, -0.5f,  0.5f), DirectX::XMFLOAT3A( 0.0f, -1.0f, 0.0f), DirectX::XMFLOAT2A(0.0f, 0.0f) }, // -Y (bottom face)
        { DirectX::XMFLOAT3A( 0.5f, -0.5f,  0.5f), DirectX::XMFLOAT3A( 0.0f, -1.0f, 0.0f), DirectX::XMFLOAT2A(1.0f, 0.0f) },
        { DirectX::XMFLOAT3A( 0.5f, -0.5f, -0.5f), DirectX::XMFLOAT3A( 0.0f, -1.0f, 0.0f), DirectX::XMFLOAT2A(1.0f, 1.0f) },
        { DirectX::XMFLOAT3A(-0.5f, -0.5f, -0.5f), DirectX::XMFLOAT3A( 0.0f, -1.0f, 0.0f), DirectX::XMFLOAT2A(0.0f, 1.0f) },

        { DirectX::XMFLOAT3A( 0.5f,  0.5f,  0.5f), DirectX::XMFLOAT3A( 1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2A(0.0f, 0.0f) }, // +X (right face)
        { DirectX::XMFLOAT3A( 0.5f,  0.5f, -0.5f), DirectX::XMFLOAT3A( 1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2A(1.0f, 0.0f) },
        { DirectX::XMFLOAT3A( 0.5f, -0.5f, -0.5f), DirectX::XMFLOAT3A( 1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2A(1.0f, 1.0f) },
        { DirectX::XMFLOAT3A( 0.5f, -0.5f,  0.5f), DirectX::XMFLOAT3A( 1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2A(0.0f, 1.0f) },

        { DirectX::XMFLOAT3A(-0.5f,  0.5f, -0.5f), DirectX::XMFLOAT3A(-1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2A(0.0f, 0.0f) }, // -X (left face)
        { DirectX::XMFLOAT3A(-0.5f,  0.5f,  0.5f), DirectX::XMFLOAT3A(-1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2A(1.0f, 0.0f) },
        { DirectX::XMFLOAT3A(-0.5f, -0.5f,  0.5f), DirectX::XMFLOAT3A(-1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2A(1.0f, 1.0f) },
        { DirectX::XMFLOAT3A(-0.5f, -0.5f, -0.5f), DirectX::XMFLOAT3A(-1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2A(0.0f, 1.0f) },

        { DirectX::XMFLOAT3A(-0.5f,  0.5f,  0.5f), DirectX::XMFLOAT3A( 0.0f, 0.0f, 1.0f), DirectX::XMFLOAT2A(0.0f, 0.0f) }, // +Z (front face)
        { DirectX::XMFLOAT3A( 0.5f,  0.5f,  0.5f), DirectX::XMFLOAT3A( 0.0f, 0.0f, 1.0f), DirectX::XMFLOAT2A(1.0f, 0.0f) },
        { DirectX::XMFLOAT3A( 0.5f, -0.5f,  0.5f), DirectX::XMFLOAT3A( 0.0f, 0.0f, 1.0f), DirectX::XMFLOAT2A(1.0f, 1.0f) },
        { DirectX::XMFLOAT3A(-0.5f, -0.5f,  0.5f), DirectX::XMFLOAT3A( 0.0f, 0.0f, 1.0f), DirectX::XMFLOAT2A(0.0f, 1.0f) },

        { DirectX::XMFLOAT3A( 0.5f,  0.5f, -0.5f), DirectX::XMFLOAT3A( 0.0f, 0.0f, -1.0f), DirectX::XMFLOAT2A(0.0f, 0.0f) }, // -Z (back face)
        { DirectX::XMFLOAT3A(-0.5f,  0.5f, -0.5f), DirectX::XMFLOAT3A( 0.0f, 0.0f, -1.0f), DirectX::XMFLOAT2A(1.0f, 0.0f) },
        { DirectX::XMFLOAT3A(-0.5f, -0.5f, -0.5f), DirectX::XMFLOAT3A( 0.0f, 0.0f, -1.0f), DirectX::XMFLOAT2A(1.0f, 1.0f) },
        { DirectX::XMFLOAT3A( 0.5f, -0.5f, -0.5f), DirectX::XMFLOAT3A( 0.0f, 0.0f, -1.0f), DirectX::XMFLOAT2A(0.0f, 1.0f) },
    };

    UInt16 CubeIndices[] =
    {
        0, 1, 2,
        0, 2, 3,

        4, 5, 6,
        4, 6, 7,

        8, 9, 10,
        8, 10, 11,

        12, 13, 14,
        12, 14, 15,

        16, 17, 18,
        16, 18, 19,

        20, 21, 22,
        20, 22, 23
    };

    CreateVertexBuffer(
        _In_ ARRAYSIZE(CubeVertices),
        _In_ CubeVertices,
        _Outptr_opt_result_nullonfailure_ ppVertexBuffer
        );

    CreateIndexBuffer(
        ARRAYSIZE(CubeIndices),
        CubeIndices,
        ppIndexBuffer
        );

    if ( uiVertexCount != nullptr ) (*uiVertexCount) = ARRAYSIZE(CubeVertices);
    if ( uiIndexCount != nullptr ) (*uiIndexCount) = ARRAYSIZE(CubeIndices);
}


Void BasicShapes::CreateBox(
    _In_ DirectX::XMFLOAT3 Radii,
    _Out_ BufferAddress ppVertexBuffer,
    _Out_ BufferAddress ppIndexBuffer,
    _Out_opt_ UInt32Ptr uiVertexCount,
    _Out_opt_ UInt32Ptr uiIndexCount
    )
{
    BasicVertex BoxVertices[] =
    {
        // FLOOR
        {DirectX::XMFLOAT3A(-Radii.x, -Radii.y,  Radii.z), DirectX::XMFLOAT3A(0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2A(0.0f, 0.0f)},
        {DirectX::XMFLOAT3A( Radii.x, -Radii.y,  Radii.z), DirectX::XMFLOAT3A(0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2A(1.0f, 0.0f)},
        {DirectX::XMFLOAT3A(-Radii.x, -Radii.y, -Radii.z), DirectX::XMFLOAT3A(0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2A(0.0f, 1.5f)},
        {DirectX::XMFLOAT3A( Radii.x, -Radii.y, -Radii.z), DirectX::XMFLOAT3A(0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2A(1.0f, 1.5f)},
        // WALL
        {DirectX::XMFLOAT3A(-Radii.x,  Radii.y, Radii.z), DirectX::XMFLOAT3A(0.0f, 0.0f, -1.0f), DirectX::XMFLOAT2A(0.0f, 0.0f)},
        {DirectX::XMFLOAT3A( Radii.x,  Radii.y, Radii.z), DirectX::XMFLOAT3A(0.0f, 0.0f, -1.0f), DirectX::XMFLOAT2A(2.0f, 0.0f)},
        {DirectX::XMFLOAT3A(-Radii.x, -Radii.y, Radii.z), DirectX::XMFLOAT3A(0.0f, 0.0f, -1.0f), DirectX::XMFLOAT2A(0.0f, 1.5f)},
        {DirectX::XMFLOAT3A( Radii.x, -Radii.y, Radii.z), DirectX::XMFLOAT3A(0.0f, 0.0f, -1.0f), DirectX::XMFLOAT2A(2.0f, 1.5f)},
        // WALL
        {DirectX::XMFLOAT3A(Radii.x,  Radii.y,  Radii.z), DirectX::XMFLOAT3A(-1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2A(0.0f, 0.0f)},
        {DirectX::XMFLOAT3A(Radii.x,  Radii.y, -Radii.z), DirectX::XMFLOAT3A(-1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2A(Radii.y,  0.0f)},
        {DirectX::XMFLOAT3A(Radii.x, -Radii.y,  Radii.z), DirectX::XMFLOAT3A(-1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2A(0.0f, 1.5f)},
        {DirectX::XMFLOAT3A(Radii.x, -Radii.y, -Radii.z), DirectX::XMFLOAT3A(-1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2A(Radii.y,  1.5f)},
        // WALL
        {DirectX::XMFLOAT3A( Radii.x,  Radii.y, -Radii.z), DirectX::XMFLOAT3A(0.0f, 0.0f, 1.0f), DirectX::XMFLOAT2A(0.0f, 0.0f)},
        {DirectX::XMFLOAT3A(-Radii.x,  Radii.y, -Radii.z), DirectX::XMFLOAT3A(0.0f, 0.0f, 1.0f), DirectX::XMFLOAT2A(2.0f, 0.0f)},
        {DirectX::XMFLOAT3A( Radii.x, -Radii.y, -Radii.z), DirectX::XMFLOAT3A(0.0f, 0.0f, 1.0f), DirectX::XMFLOAT2A(0.0f, 1.5f)},
        {DirectX::XMFLOAT3A(-Radii.x, -Radii.y, -Radii.z), DirectX::XMFLOAT3A(0.0f, 0.0f, 1.0f), DirectX::XMFLOAT2A(2.0f, 1.5f)},
        // WALL
        {DirectX::XMFLOAT3A(-Radii.x,  Radii.y, -Radii.z), DirectX::XMFLOAT3A(1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2A(0.0f, 0.0f)},
        {DirectX::XMFLOAT3A(-Radii.x,  Radii.y,  Radii.z), DirectX::XMFLOAT3A(1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2A(Radii.y,  0.0f)},
        {DirectX::XMFLOAT3A(-Radii.x, -Radii.y, -Radii.z), DirectX::XMFLOAT3A(1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2A(0.0f, 1.5f)},
        {DirectX::XMFLOAT3A(-Radii.x, -Radii.y,  Radii.z), DirectX::XMFLOAT3A(1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2A(Radii.y,  1.5f)},
        // CEILING
        {DirectX::XMFLOAT3A(-Radii.x, Radii.y, -Radii.z), DirectX::XMFLOAT3A(0.0f, -1.0f, 0.0f), DirectX::XMFLOAT2A(-0.15f, 0.0f)},
        {DirectX::XMFLOAT3A( Radii.x, Radii.y, -Radii.z), DirectX::XMFLOAT3A(0.0f, -1.0f, 0.0f), DirectX::XMFLOAT2A( 1.25f, 0.0f)},
        {DirectX::XMFLOAT3A(-Radii.x, Radii.y,  Radii.z), DirectX::XMFLOAT3A(0.0f, -1.0f, 0.0f), DirectX::XMFLOAT2A(-0.15f, 2.1f)},
        {DirectX::XMFLOAT3A( Radii.x, Radii.y,  Radii.z), DirectX::XMFLOAT3A(0.0f, -1.0f, 0.0f), DirectX::XMFLOAT2A( 1.25f, 2.1f)},
    };

    UInt16 BoxIndices[] =
    {
        0, 2, 1,
        1, 2, 3,

        4, 6, 5,
        5, 6, 7,

        8, 10, 9,
        9, 10, 11,

        12, 14, 13,
        13, 14, 15,

        16, 18, 17,
        17, 18, 19,

        20, 22, 21,
        21, 22, 23,
    };

    CreateVertexBuffer(
        _In_ ARRAYSIZE(BoxVertices),
        _In_ BoxVertices,
        _Outptr_opt_result_nullonfailure_ ppVertexBuffer
        );

    CreateIndexBuffer(
        _In_ ARRAYSIZE(BoxIndices),
        _In_ BoxIndices,
        _Outptr_opt_result_nullonfailure_ ppIndexBuffer
        );

    if ( uiVertexCount != nullptr ) (*uiVertexCount) = ARRAYSIZE(BoxVertices);
    if ( uiIndexCount != nullptr ) (*uiIndexCount) = ARRAYSIZE(BoxIndices);
}


Void BasicShapes::CreateSphere(
    _Out_ BufferAddress ppVertexBuffer,
    _Out_ BufferAddress ppIndexBuffer,
    _Out_opt_ UInt32Ptr uiVertexCount,
    _Out_opt_ UInt32Ptr uiIndexCount
    )
{
	UInt32Const uNumSegments = 64;
    UInt32Const uNumSlices = uNumSegments / 2;

    UInt32Const uNumVertices = (uNumSlices + 1) * (uNumSegments + 1);
    std::unique_ptr<BasicVertex[]> SphereVertices(
		new BasicVertex[uNumVertices]
		);

    for ( auto uSlice = 0u; uSlice <= uNumSlices; uSlice++ )
    {
        auto fV = (Float32)uSlice / (Float32)uNumSlices;
        auto fInclination = fV * DirectX::XM_PI;
        auto fY = cos(fInclination);
        auto fR = sin(fInclination);

        for ( auto uSegment = 0u; uSegment <= uNumSegments; uSegment++ )
        {
            auto uIndex = uSlice * (uNumSegments + 1) + uSegment;
            auto fU = (Float32)uSegment / (Float32)uNumSegments;
            auto fAzimuth = fU * DirectX::XM_2PI;

            SphereVertices[uIndex].Pos = DirectX::XMFLOAT3A(fR * sin(fAzimuth), fY, fR * cos(fAzimuth));
            SphereVertices[uIndex].Norm = SphereVertices[uIndex].Pos;
            SphereVertices[uIndex].Tex = DirectX::XMFLOAT2A(fU, fV);
        }
    }

    UInt32Const uNumIndices = uNumSlices * (uNumSegments - 2) * 6;
    std::unique_ptr<UInt16[]> SphereIndices(
		new UInt16[uNumIndices]
		);

    UInt32 uIndex = 0u;
    for ( auto uSlice = 0u; uSlice < uNumSlices; uSlice++)
    {
        auto uSliceBase0 = (UInt16)((uSlice) * (uNumSegments + 1));
        auto uSliceBase1 = (UInt16)((uSlice + 1) * (uNumSegments + 1));

        for ( auto uSegment = 0u; uSegment < uNumSegments; uSegment++)
        {
            if (uSlice > 0)
            {
                SphereIndices[uIndex++] = uSliceBase0 + uSegment;
                SphereIndices[uIndex++] = uSliceBase0 + uSegment + 1;
                SphereIndices[uIndex++] = uSliceBase1 + uSegment + 1;
            }
            if (uSlice < uNumSlices-1)
            {
                SphereIndices[uIndex++] = uSliceBase0 + uSegment;
                SphereIndices[uIndex++] = uSliceBase0 + uSegment + 1;
                SphereIndices[uIndex++] = uSliceBase1 + uSegment;
            }
        }
    }

    CreateVertexBuffer(
        _In_ uNumVertices, _In_ SphereVertices.get(),
        _Outptr_opt_result_nullonfailure_ ppVertexBuffer
        );
    CreateIndexBuffer(
        _In_ uNumIndices, _In_ SphereIndices.get(),
        _Outptr_opt_result_nullonfailure_ ppIndexBuffer
        );

    if ( uiVertexCount != nullptr ) (*uiVertexCount) = uNumVertices;
    if ( uiIndexCount != nullptr ) (*uiIndexCount) = uNumIndices;
}

Void BasicShapes::CreateTangentSphere(
    _Out_ BufferAddress ppVertexBuffer,
    _Out_ BufferAddress ppIndexBuffer,
    _Out_opt_ UInt32Ptr uiVertexCount,
    _Out_opt_ UInt32Ptr uiIndexCount
    )
{
	UInt32Const uNumSegments = 64;
    UInt32Const uNumSlices = uNumSegments / 2;

    UInt32Const uNumVertices = (uNumSlices + 1) * (uNumSegments + 1);
    std::unique_ptr<TangentVertex[]> SphereVertices(
		new TangentVertex[uNumVertices]
		);

    for ( auto uSlice = 0u; uSlice <= uNumSlices; uSlice++ )
    {
        auto fV = (Float32)uSlice / (Float32)uNumSlices;
        auto fInclination = fV * DirectX::XM_PI;
        auto fY = cos(fInclination);
        auto fR = sin(fInclination);

        for ( auto uSegment = 0u; uSegment <= uNumSegments; uSegment++ )
        {
            auto uIndex = uSlice * (uNumSegments + 1) + uSegment;
            auto fU = (Float32)uSegment / (Float32)uNumSegments;
            auto fAzimuth = fU * DirectX::XM_2PI;

            SphereVertices[uIndex].VTan = DirectX::XMFLOAT3A(cos(fInclination)*sin(fAzimuth), -sin(fInclination), cos(fInclination)*cos(fAzimuth));
            SphereVertices[uIndex].Pos = DirectX::XMFLOAT3A(fR * sin(fAzimuth), fY, fR * cos(fAzimuth));
            SphereVertices[uIndex].UTan = DirectX::XMFLOAT3A(cos(fAzimuth), 0, -sin(fAzimuth));
            SphereVertices[uIndex].Tex = DirectX::XMFLOAT2A(fU, fV);
        }
    }

    UInt32Const uNumIndices = uNumSlices * (uNumSegments - 2) * 6;
    std::unique_ptr<UInt16[]> SphereIndices(
		new UInt16[uNumIndices]
		);

    UInt32 uIndex = 0u;
    for ( auto uSlice = 0u; uSlice < uNumSlices; uSlice++)
    {
        auto uSliceBase0 = (UInt16)((uSlice) * (uNumSegments + 1));
        auto uSliceBase1 = (UInt16)((uSlice + 1) * (uNumSegments + 1));

        for ( auto uSegment = 0u; uSegment < uNumSegments; uSegment++)
        {
            if (uSlice > 0)
            {
                SphereIndices[uIndex++] = uSliceBase0 + uSegment;
                SphereIndices[uIndex++] = uSliceBase0 + uSegment + 1;
                SphereIndices[uIndex++] = uSliceBase1 + uSegment + 1;
            }
            if (uSlice < uNumSlices-1)
            {
                SphereIndices[uIndex++] = uSliceBase0 + uSegment;
                SphereIndices[uIndex++] = uSliceBase0 + uSegment + 1;
                SphereIndices[uIndex++] = uSliceBase1 + uSegment;
            }
        }
    }

    CreateTangentVertexBuffer(
        _In_ uNumVertices, _In_ SphereVertices.get(),
        _Outptr_opt_result_nullonfailure_ ppVertexBuffer
        );
    CreateIndexBuffer(
        _In_ uNumIndices, _In_ SphereIndices.get(),
        _Outptr_opt_result_nullonfailure_ ppIndexBuffer
        );

    if ( uiVertexCount != nullptr ) (*uiVertexCount) = uNumVertices;
    if ( uiIndexCount != nullptr ) (*uiIndexCount) = uNumIndices;
}

Void BasicShapes::CreateReferenceAxis(
    _Out_ BufferAddress ppVertexBuffer,
    _Out_ BufferAddress ppIndexBuffer,
    _Out_opt_ UInt32Ptr uiVertexCount,
    _Out_opt_ UInt32Ptr uiIndexCount
    )
{
    BasicVertex AxisVertices[] =
    {
        { DirectX::XMFLOAT3A( 0.500f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.125f, 0.500f, 0.500f), DirectX::XMFLOAT2A(0.250f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.125f, 0.000f), DirectX::XMFLOAT3A( 0.125f, 0.500f, 0.500f), DirectX::XMFLOAT2A(0.250f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.125f), DirectX::XMFLOAT3A( 0.125f, 0.500f, 0.500f), DirectX::XMFLOAT2A(0.250f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.500f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.125f,-0.500f, 0.500f), DirectX::XMFLOAT2A(0.250f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.125f), DirectX::XMFLOAT3A( 0.125f,-0.500f, 0.500f), DirectX::XMFLOAT2A(0.250f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f,-0.125f, 0.000f), DirectX::XMFLOAT3A( 0.125f,-0.500f, 0.500f), DirectX::XMFLOAT2A(0.250f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.500f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.125f,-0.500f,-0.500f), DirectX::XMFLOAT2A(0.250f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f,-0.125f, 0.000f), DirectX::XMFLOAT3A( 0.125f,-0.500f,-0.500f), DirectX::XMFLOAT2A(0.250f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.125f), DirectX::XMFLOAT3A( 0.125f,-0.500f,-0.500f), DirectX::XMFLOAT2A(0.250f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.500f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.125f, 0.500f,-0.500f), DirectX::XMFLOAT2A(0.250f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.125f), DirectX::XMFLOAT3A( 0.125f, 0.500f,-0.500f), DirectX::XMFLOAT2A(0.250f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.125f, 0.000f), DirectX::XMFLOAT3A( 0.125f, 0.500f,-0.500f), DirectX::XMFLOAT2A(0.250f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.125f, 0.000f), DirectX::XMFLOAT3A(-0.125f, 0.000f, 0.000f), DirectX::XMFLOAT2A(0.250f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.125f), DirectX::XMFLOAT3A(-0.125f, 0.000f, 0.000f), DirectX::XMFLOAT2A(0.250f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f,-0.125f, 0.000f), DirectX::XMFLOAT3A(-0.125f, 0.000f, 0.000f), DirectX::XMFLOAT2A(0.250f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.125f), DirectX::XMFLOAT3A(-0.125f, 0.000f, 0.000f), DirectX::XMFLOAT2A(0.250f, 0.250f) },
        { DirectX::XMFLOAT3A(-0.500f, 0.000f, 0.000f), DirectX::XMFLOAT3A(-0.125f, 0.500f, 0.500f), DirectX::XMFLOAT2A(0.250f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.125f), DirectX::XMFLOAT3A(-0.125f, 0.500f, 0.500f), DirectX::XMFLOAT2A(0.250f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.125f, 0.000f), DirectX::XMFLOAT3A(-0.125f, 0.500f, 0.500f), DirectX::XMFLOAT2A(0.250f, 0.500f) },
        { DirectX::XMFLOAT3A(-0.500f, 0.000f, 0.000f), DirectX::XMFLOAT3A(-0.125f, 0.500f,-0.500f), DirectX::XMFLOAT2A(0.250f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.125f, 0.000f), DirectX::XMFLOAT3A(-0.125f, 0.500f,-0.500f), DirectX::XMFLOAT2A(0.250f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.125f), DirectX::XMFLOAT3A(-0.125f, 0.500f,-0.500f), DirectX::XMFLOAT2A(0.250f, 0.500f) },
        { DirectX::XMFLOAT3A(-0.500f, 0.000f, 0.000f), DirectX::XMFLOAT3A(-0.125f,-0.500f,-0.500f), DirectX::XMFLOAT2A(0.250f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.125f), DirectX::XMFLOAT3A(-0.125f,-0.500f,-0.500f), DirectX::XMFLOAT2A(0.250f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f,-0.125f, 0.000f), DirectX::XMFLOAT3A(-0.125f,-0.500f,-0.500f), DirectX::XMFLOAT2A(0.250f, 0.500f) },
        { DirectX::XMFLOAT3A(-0.500f, 0.000f, 0.000f), DirectX::XMFLOAT3A(-0.125f,-0.500f, 0.500f), DirectX::XMFLOAT2A(0.250f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f,-0.125f, 0.000f), DirectX::XMFLOAT3A(-0.125f,-0.500f, 0.500f), DirectX::XMFLOAT2A(0.250f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.125f), DirectX::XMFLOAT3A(-0.125f,-0.500f, 0.500f), DirectX::XMFLOAT2A(0.250f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.125f), DirectX::XMFLOAT3A( 0.125f, 0.000f, 0.000f), DirectX::XMFLOAT2A(0.250f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f,-0.125f, 0.000f), DirectX::XMFLOAT3A( 0.125f, 0.000f, 0.000f), DirectX::XMFLOAT2A(0.250f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.125f), DirectX::XMFLOAT3A( 0.125f, 0.000f, 0.000f), DirectX::XMFLOAT2A(0.250f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.125f, 0.000f), DirectX::XMFLOAT3A( 0.125f, 0.000f, 0.000f), DirectX::XMFLOAT2A(0.250f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.500f, 0.000f), DirectX::XMFLOAT3A( 0.500f, 0.125f, 0.500f), DirectX::XMFLOAT2A(0.500f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.125f), DirectX::XMFLOAT3A( 0.500f, 0.125f, 0.500f), DirectX::XMFLOAT2A(0.500f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.500f, 0.125f, 0.500f), DirectX::XMFLOAT2A(0.500f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.500f, 0.000f), DirectX::XMFLOAT3A( 0.500f, 0.125f,-0.500f), DirectX::XMFLOAT2A(0.500f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.500f, 0.125f,-0.500f), DirectX::XMFLOAT2A(0.500f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.125f), DirectX::XMFLOAT3A( 0.500f, 0.125f,-0.500f), DirectX::XMFLOAT2A(0.500f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.500f, 0.000f), DirectX::XMFLOAT3A(-0.500f, 0.125f,-0.500f), DirectX::XMFLOAT2A(0.500f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.125f), DirectX::XMFLOAT3A(-0.500f, 0.125f,-0.500f), DirectX::XMFLOAT2A(0.500f, 0.250f) },
        { DirectX::XMFLOAT3A(-0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A(-0.500f, 0.125f,-0.500f), DirectX::XMFLOAT2A(0.500f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.500f, 0.000f), DirectX::XMFLOAT3A(-0.500f, 0.125f, 0.500f), DirectX::XMFLOAT2A(0.500f, 0.250f) },
        { DirectX::XMFLOAT3A(-0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A(-0.500f, 0.125f, 0.500f), DirectX::XMFLOAT2A(0.500f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.125f), DirectX::XMFLOAT3A(-0.500f, 0.125f, 0.500f), DirectX::XMFLOAT2A(0.500f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.000f,-0.125f, 0.000f), DirectX::XMFLOAT2A(0.500f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.125f), DirectX::XMFLOAT3A( 0.000f,-0.125f, 0.000f), DirectX::XMFLOAT2A(0.500f, 0.250f) },
        { DirectX::XMFLOAT3A(-0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.000f,-0.125f, 0.000f), DirectX::XMFLOAT2A(0.500f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.125f), DirectX::XMFLOAT3A( 0.000f,-0.125f, 0.000f), DirectX::XMFLOAT2A(0.500f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f,-0.500f, 0.000f), DirectX::XMFLOAT3A( 0.500f,-0.125f, 0.500f), DirectX::XMFLOAT2A(0.500f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.500f,-0.125f, 0.500f), DirectX::XMFLOAT2A(0.500f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.125f), DirectX::XMFLOAT3A( 0.500f,-0.125f, 0.500f), DirectX::XMFLOAT2A(0.500f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f,-0.500f, 0.000f), DirectX::XMFLOAT3A(-0.500f,-0.125f, 0.500f), DirectX::XMFLOAT2A(0.500f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.125f), DirectX::XMFLOAT3A(-0.500f,-0.125f, 0.500f), DirectX::XMFLOAT2A(0.500f, 0.500f) },
        { DirectX::XMFLOAT3A(-0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A(-0.500f,-0.125f, 0.500f), DirectX::XMFLOAT2A(0.500f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f,-0.500f, 0.000f), DirectX::XMFLOAT3A(-0.500f,-0.125f,-0.500f), DirectX::XMFLOAT2A(0.500f, 0.500f) },
        { DirectX::XMFLOAT3A(-0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A(-0.500f,-0.125f,-0.500f), DirectX::XMFLOAT2A(0.500f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.125f), DirectX::XMFLOAT3A(-0.500f,-0.125f,-0.500f), DirectX::XMFLOAT2A(0.500f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f,-0.500f, 0.000f), DirectX::XMFLOAT3A( 0.500f,-0.125f,-0.500f), DirectX::XMFLOAT2A(0.500f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.125f), DirectX::XMFLOAT3A( 0.500f,-0.125f,-0.500f), DirectX::XMFLOAT2A(0.500f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.500f,-0.125f,-0.500f), DirectX::XMFLOAT2A(0.500f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.125f), DirectX::XMFLOAT3A( 0.000f, 0.125f, 0.000f), DirectX::XMFLOAT2A(0.500f, 0.500f) },
        { DirectX::XMFLOAT3A(-0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.000f, 0.125f, 0.000f), DirectX::XMFLOAT2A(0.500f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.125f), DirectX::XMFLOAT3A( 0.000f, 0.125f, 0.000f), DirectX::XMFLOAT2A(0.500f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.000f, 0.125f, 0.000f), DirectX::XMFLOAT2A(0.500f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.500f), DirectX::XMFLOAT3A( 0.500f, 0.500f, 0.125f), DirectX::XMFLOAT2A(0.750f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.500f, 0.500f, 0.125f), DirectX::XMFLOAT2A(0.750f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.125f, 0.000f), DirectX::XMFLOAT3A( 0.500f, 0.500f, 0.125f), DirectX::XMFLOAT2A(0.750f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.500f), DirectX::XMFLOAT3A(-0.500f, 0.500f, 0.125f), DirectX::XMFLOAT2A(0.750f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.125f, 0.000f), DirectX::XMFLOAT3A(-0.500f, 0.500f, 0.125f), DirectX::XMFLOAT2A(0.750f, 0.250f) },
        { DirectX::XMFLOAT3A(-0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A(-0.500f, 0.500f, 0.125f), DirectX::XMFLOAT2A(0.750f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.500f), DirectX::XMFLOAT3A(-0.500f,-0.500f, 0.125f), DirectX::XMFLOAT2A(0.750f, 0.250f) },
        { DirectX::XMFLOAT3A(-0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A(-0.500f,-0.500f, 0.125f), DirectX::XMFLOAT2A(0.750f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f,-0.125f, 0.000f), DirectX::XMFLOAT3A(-0.500f,-0.500f, 0.125f), DirectX::XMFLOAT2A(0.750f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.500f), DirectX::XMFLOAT3A( 0.500f,-0.500f, 0.125f), DirectX::XMFLOAT2A(0.750f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f,-0.125f, 0.000f), DirectX::XMFLOAT3A( 0.500f,-0.500f, 0.125f), DirectX::XMFLOAT2A(0.750f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.500f,-0.500f, 0.125f), DirectX::XMFLOAT2A(0.750f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.125f), DirectX::XMFLOAT2A(0.750f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f,-0.125f, 0.000f), DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.125f), DirectX::XMFLOAT2A(0.750f, 0.250f) },
        { DirectX::XMFLOAT3A(-0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.125f), DirectX::XMFLOAT2A(0.750f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.125f, 0.000f), DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.125f), DirectX::XMFLOAT2A(0.750f, 0.250f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.500f), DirectX::XMFLOAT3A( 0.500f, 0.500f,-0.125f), DirectX::XMFLOAT2A(0.750f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.125f, 0.000f), DirectX::XMFLOAT3A( 0.500f, 0.500f,-0.125f), DirectX::XMFLOAT2A(0.750f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.500f, 0.500f,-0.125f), DirectX::XMFLOAT2A(0.750f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.500f), DirectX::XMFLOAT3A( 0.500f,-0.500f,-0.125f), DirectX::XMFLOAT2A(0.750f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.500f,-0.500f,-0.125f), DirectX::XMFLOAT2A(0.750f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f,-0.125f, 0.000f), DirectX::XMFLOAT3A( 0.500f,-0.500f,-0.125f), DirectX::XMFLOAT2A(0.750f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.500f), DirectX::XMFLOAT3A(-0.500f,-0.500f,-0.125f), DirectX::XMFLOAT2A(0.750f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f,-0.125f, 0.000f), DirectX::XMFLOAT3A(-0.500f,-0.500f,-0.125f), DirectX::XMFLOAT2A(0.750f, 0.500f) },
        { DirectX::XMFLOAT3A(-0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A(-0.500f,-0.500f,-0.125f), DirectX::XMFLOAT2A(0.750f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.000f,-0.500f), DirectX::XMFLOAT3A(-0.500f, 0.500f,-0.125f), DirectX::XMFLOAT2A(0.750f, 0.500f) },
        { DirectX::XMFLOAT3A(-0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A(-0.500f, 0.500f,-0.125f), DirectX::XMFLOAT2A(0.750f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.125f, 0.000f), DirectX::XMFLOAT3A(-0.500f, 0.500f,-0.125f), DirectX::XMFLOAT2A(0.750f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f, 0.125f, 0.000f), DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.125f), DirectX::XMFLOAT2A(0.750f, 0.500f) },
        { DirectX::XMFLOAT3A(-0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.125f), DirectX::XMFLOAT2A(0.750f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.000f,-0.125f, 0.000f), DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.125f), DirectX::XMFLOAT2A(0.750f, 0.500f) },
        { DirectX::XMFLOAT3A( 0.125f, 0.000f, 0.000f), DirectX::XMFLOAT3A( 0.000f, 0.000f, 0.125f), DirectX::XMFLOAT2A(0.750f, 0.500f) },
    };

    UInt16 AxisIndices[] =
    {
         0,  2,  1,
         3,  5,  4,
         6,  8,  7,
         9, 11, 10,
        12, 14, 13,
        12, 15, 14,
        16, 18, 17,
        19, 21, 20,
        22, 24, 23,
        25, 27, 26,
        28, 30, 29,
        28, 31, 30,
        32, 34, 33,
        35, 37, 36,
        38, 40, 39,
        41, 43, 42,
        44, 46, 45,
        44, 47, 46,
        48, 50, 49,
        51, 53, 52,
        54, 56, 55,
        57, 59, 58,
        60, 62, 61,
        60, 63, 62,
        64, 66, 65,
        67, 69, 68,
        70, 72, 71,
        73, 75, 74,
        76, 78, 77,
        76, 79, 78,
        80, 82, 81,
        83, 85, 84,
        86, 88, 87,
        89, 91, 90,
        92, 94, 93,
        92, 95, 94,
    };

    CreateVertexBuffer(
        ARRAYSIZE(AxisVertices), AxisVertices,
        ppVertexBuffer
        );
    CreateIndexBuffer(
        ARRAYSIZE(AxisIndices), AxisIndices,
        ppIndexBuffer
        );

    if (uiVertexCount != nullptr) (*uiVertexCount) = ARRAYSIZE(AxisVertices);
    if (uiIndexCount != nullptr) (*uiIndexCount) = ARRAYSIZE(AxisIndices);
}

